import React from "react"
import GpContainer from "@/components/GpContainer"
import { Image, ScrollView, Navigator, Text, View } from "@tarojs/components"
import { Grid, Sticky } from "@taroify/core"
import { ArrowDown } from "@taroify/icons"
import clsx from "clsx"
import GpBlockTitle from "@/components/GpBlockTitle"
import Taro from "@tarojs/taro"
import GpSchoolItem from "@/components/GpSchoolItem"
import GpInstitutionItemPure from "@/components/GpInstitutionItemPure"
import GpNewsItem from "@/components/GpNewsItem"
import GpPagination from "@/components/GpPagination"
import GpJumpNavs from "@/components/GpJumpNavs"
import GpCurrentPort from "@/components/GpCurrentPort"
import GpSimpleTabbar from "@/components/GpSimpleTabbar"
import { getSchoolDetail } from "@/apis/index"
import { pageMapper, PagePath } from "@/constants/pageMap"
import { commonUrls, makePagePath, navigation } from "@/utils/router"
import { cloneDeep, debounce, setPageMeta } from "@/utils/common"
import GpEmpty from "@/components/GpEmpty"
import GpHtmlRenderer from "@/components/GpHtmlRenderer"
import styles from "./index.module.scss"

const proPageSize = 8
const htmlContentHeightThreshold = 100
enum SelectorKey {
  /** 简介 */
  intro = "intro",
  /** 专业 */
  prof = "prof",
  /** 简章 */
  badge = "badge",
  /** 资讯 */
  news = "news"
}
const ports = [{ text: "学校详情" }]
const arrowSize = Taro.pxTransform(28)
type ITopTabbar = {
  text: string
  selector: SelectorKey
  scrollTop?: number
}
const topTabbarMap = [
  { text: "简介", selector: SelectorKey.intro },
  { text: "专业", selector: SelectorKey.prof },
  { text: "简章", selector: SelectorKey.badge },
  { text: "资讯", selector: SelectorKey.news }
]
type IDetail = {
  id: number
  name: string
  logo: string
  province: string
  features: string[]
  level: string
  department: string
  banner: string
  description: IHtmlBlockContentable["content"]
}
type IState = {
  topTabbars: ITopTabbar[]
  currentActiveTab: SelectorKey
  htmlContentHeight: number
  showAllHtmlContent: boolean
  detail: IDetail | null
  /** 招生专业 */
  subjects__show: any[]
  /** 招生简章 */
  recruitNews: any[]
  /** 相关资讯 */
  news: any[]
  /** 推荐机构 */
  agencys: any[]
  /** 周边院校 */
  schools: any[]
  /** 艺考专题 */
  topics: any[]
  /** 顶部tabbar是否有下阴影 */
  topTabbarShadow: boolean
  htmlContentMaxHeight: number
  subjectPagination: IPagination
}
type IData = {
  id: string
  /** 顶部tabbar的top 单位px*/
  topTabbarsTop: number
  /** 顶部tabbar的高度 单位px*/
  topTabbarsHeight: number
  handleScrollTriggered: boolean
  fetchedAndReadyTimer: INullable<ReturnType<typeof setTimeout>>
  dateFetched: boolean
  pageIsReady: boolean
  /** 可使用窗口高度，单位px */
  windowAvailableHeight: number
  /** 招生专业 */
  subjects: any[]
}
class SchoolDetail extends React.Component<unknown, IState> {
  extData: IData
  constructor(props) {
    super(props)
    this.state = {
      currentActiveTab: SelectorKey.intro,
      topTabbars: topTabbarMap,
      htmlContentHeight: 0,
      showAllHtmlContent: false,
      detail: null,
      subjects__show: [],
      recruitNews: [],
      news: [],
      agencys: [],
      schools: [],
      topics: [],
      topTabbarShadow: false,
      htmlContentMaxHeight: 100,
      subjectPagination: {
        page: 1,
        pageCount: 1
      }
    }
    this.extData = {
      id: "",
      topTabbarsHeight: 0,
      topTabbarsTop: 0,
      handleScrollTriggered: false,
      fetchedAndReadyTimer: null,
      dateFetched: false,
      pageIsReady: false,
      windowAvailableHeight: 0,
      subjects: []
    }
    // throttle page scroll
    this.pageScrollHandler = debounce(this.pageScrollHandler.bind(this), 300)
  }
  onShareAppMessage() {}
  getWindowAvailableHeight = () => {
    try {
      const res = Taro.getSystemInfoSync()
      this.extData.windowAvailableHeight = res.windowHeight
    } catch (e) {
      console.log("[getWindowAvailableHeight]: error", e)
    }
  }
  onLoad(options: Recordable) {
    this.extData.id = options.id
    this.getWindowAvailableHeight()
    this.startLayoutTimer()
    this.getDetailData()
  }
  componentDidShow() {
    this.setPageInfo(this.state.detail)
  }
  setPageInfo = (detail: INullable<IDetail>) => {
    if (detail) {
      setPageMeta({
        keywords: `${detail.name}，${detail.name}艺术专业，${detail.name}艺考招生简章`,
        description: `${detail.name}艺考招生信息网-择艺宝为你分享${detail.name}艺术类院校简介、艺考招生专业、艺考招生简章、艺考招生动态与政策等相关资讯信息。`,
        title: `${detail.name}艺考招生信息网-择艺宝`
      })
    }
  }
  componentWillUnmount() {
    // avoid memory leak but `onunload` will be better, but current Taro version does not support `onunload`
    // see https://taro-docs.jd.com/taro/docs/react-page#onunload-
    this.closeLayoutTimer()
  }
  startLayoutTimer = () => {
    this.extData.fetchedAndReadyTimer = setTimeout(() => {
      this.queryLayoutActionTask()
    }, 300)
  }
  closeLayoutTimer = () => {
    if (this.extData.fetchedAndReadyTimer !== null) {
      clearTimeout(this.extData.fetchedAndReadyTimer)
      this.extData.fetchedAndReadyTimer = null
      console.log("[closeLayoutTimer] triggered")
    }
  }
  queryLayoutActionTask = () => {
    const { dateFetched, pageIsReady } = this.extData
    if (dateFetched && pageIsReady) {
      this.closeLayoutTimer()
      Taro.nextTick(() => {
        this.doLayoutAction()
      })
    } else {
      this.startLayoutTimer()
    }
  }
  handleJump = (path: PagePath, query: INullable<Recordable>) => {
    navigation(path, query)
  }
  /** 招生专业 */
  renderProfessional = () => {
    const { subjects__show, subjectPagination } = this.state
    if (subjects__show.length <= 0) return null
    return (
      <View className="pt-88px bg-white">
        <View className="pb-34px px-30px" id={SelectorKey.prof}>
          <GpBlockTitle title="招生专业" />
        </View>
        <View className="">
          <View className="px-30px">
            <View className={styles["profession-grid"]}>
              {subjects__show.map((l, index) => (
                <Grid.Item key={index}>
                  <View
                    onClick={() => this.handleJump(pageMapper.proIntro, { id: l.id })}
                    className={clsx(
                      "rounded-12px bg-hex-fafafd h-131px w-333px box-border py-24px px-32px flex flex-col justify-center"
                    )}
                  >
                    <Text className="yahei font-normal text-30px text-hex-2c2c35 whitespace-nowrap truncate">
                      {l.name}
                    </Text>
                    <View className="yahei font-normal text-24px text-hex-b8b8bf mt-12px">
                      <Text>专业代码:{l.code}</Text>
                    </View>
                  </View>
                </Grid.Item>
              ))}
            </View>
          </View>
        </View>
        {/* 分液器 */}
        <GpPagination onChange={this.handleProPageChange} pagination={subjectPagination} />
      </View>
    )
  }
  /**  招生简章*/
  renderBadge = () => {
    const { recruitNews } = this.state
    const len = recruitNews.length
    if (len <= 0) return null
    return (
      <View className="pt-88px bg-white">
        <View className="pb-34px px-30px" id={SelectorKey.badge}>
          <GpBlockTitle title="招生简章" />
        </View>
        <View className="mt-40px px-30px pb-33px flex flex-col">
          {len > 0 ? (
            recruitNews.map((l, index) => (
              <GpNewsItem
                text={l.title}
                key={index}
                time={l.date}
                navigationLink={l.url}
                className={clsx({
                  "mb-28px": index !== len - 1
                })}
              />
            ))
          ) : (
            <GpEmpty />
          )}
        </View>
      </View>
    )
  }
  /**  相关资讯*/
  renderNews = () => {
    const { news } = this.state
    const len = news.length
    if (len <= 0) return null
    return (
      <View className="pt-88px bg-white">
        <View className="pb-34px px-30px" id={SelectorKey.news}>
          <GpBlockTitle title="相关资讯" />
        </View>
        <View className="mt-40px px-30px pb-33px flex flex-col ">
          {len > 0 ? (
            news.map((l, index) => (
              <GpNewsItem
                text={l.title}
                key={index}
                time={l.date}
                navigationLink={l.url}
                className={clsx({
                  "mb-28px": index !== len - 1
                })}
              />
            ))
          ) : (
            <GpEmpty />
          )}
        </View>
      </View>
    )
  }
  /** 推荐机构 */
  renderInstitution = () => {
    const { agencys } = this.state
    if (agencys.length <= 0) return null
    return (
      <View className="pt-88px bg-white">
        <View className="pb-34px px-30px">
          <GpBlockTitle
            title="推荐机构"
            showArrow
            navigatorLink={commonUrls.institution}
            openType="switchTab"
          />
        </View>
        <View className="px-30px flex flex-col">
          {agencys.map((l, index) => (
            <GpInstitutionItemPure key={index} showAdFlag institution={l} />
          ))}
        </View>
      </View>
    )
  }
  /** 周边院校 */
  renderSchool = () => {
    const { schools, detail } = this.state
    if (schools.length <= 0) return null
    const navigatorLink = makePagePath(pageMapper.shoolQuery, { province: detail?.province })
    return (
      <View className="pt-90px bg-white">
        <View className="pb-30px px-30px">
          <GpBlockTitle title="周边院校" showArrow navigatorLink={navigatorLink} />
        </View>
        <View className="px-30px">
          <View className="flex flex-col">
            {schools.map((l, index) => (
              <GpSchoolItem key={index} schoolItem={l} />
            ))}
          </View>
        </View>
      </View>
    )
  }
  /** 艺考专题 */
  renderExamColumn = () => {
    const { topics } = this.state
    if (topics.length <= 0) return null
    return (
      <View className="pt-87px bg-white">
        <View className="pb-34px px-30px">
          <GpBlockTitle title="艺考专题" showArrow navigatorLink={commonUrls.columnArticle} />
        </View>
        <View className="pb-32px pl-30px">
          <ScrollView scrollX scrollWithAnimation className="whitespace-nowrap">
            {topics.map((l, index) => (
              <Navigator url={l.url} className={styles["column-item"]} key={index}>
                <Image src={l.picture} className="w-478px h-239px" mode="aspectFill" />
                <View className="absolute left-0 right-0 bottom-0">
                  <View className={styles["column-item-mask"]}></View>
                  <Text className="yahei font-normal text-28px text-hex-fff pl-24px pb-16px relative leading-32px">
                    {l.title}
                  </Text>
                </View>
              </Navigator>
            ))}
          </ScrollView>
        </View>
      </View>
    )
  }
  /** 快捷导航 */
  renderJumpNavs = () => {
    return (
      <View className="mt-20px">
        <GpJumpNavs />
      </View>
    )
  }
  /**顶部tabbar */
  renderTopTabbar = () => {
    const { currentActiveTab, topTabbars, topTabbarShadow } = this.state
    const len = topTabbars.length
    return (
      <Sticky>
        <View
          className={clsx("flex flex-row  justify-center bg-white pt-30px relative", {
            [styles["shadow-bottom"]]: topTabbarShadow
          })}
          id="topTabbars"
        >
          {topTabbars.map((l, index) => (
            <View
              key={l.selector}
              className={clsx(styles["toptab-item"], {
                [styles["active"]]: l.selector === currentActiveTab,
                "mr-100px": index !== len - 1
              })}
              onClick={() => this.handleClickTopTab(l)}
            >
              {l.text}
            </View>
          ))}
        </View>
      </Sticky>
    )
  }
  handleClickTopTab = (topTab: ITopTabbar) => {
    this.extData.handleScrollTriggered = true
    Taro.pageScrollTo({
      scrollTop: topTab.scrollTop,
      duration: 300
    })
    setTimeout(() => {
      this.setState({
        currentActiveTab: topTab.selector
      })
      console.log("this.extData.handleScrollTriggered = false")
      this.extData.handleScrollTriggered = false
    }, 600)
  }
  onReady() {
    // this.getDetailData()
    this.extData.pageIsReady = true
  }
  doLayoutAction = () => {
    this.determineWXParseFold()
  }
  getDetailData = () => {
    Taro.showLoading()
    getSchoolDetail(this.extData.id)
      .then(res => {
        if (res.data.success) {
          const retData = res.data.data
          const _subjects = retData.subjects || []
          const _recruitNews = retData.recruitNews || []
          _recruitNews.forEach(l => {
            l.url = makePagePath(pageMapper.schollBadge, { id: l.id })
          })
          const _news = retData.news || []
          _news.forEach(l => {
            l.url = makePagePath(pageMapper.schollBadge, { id: l.id })
          })
          const _topics = retData.topics || []
          _topics.forEach(l => {
            l.url = makePagePath(pageMapper.columnMain, { id: l.id })
          })
          // @mark 专业 简章和资讯没数据不显示tabbar
          const _topTabbars = cloneDeep(this.state.topTabbars)
          if (_subjects.length <= 0) {
            const _index = _topTabbars.findIndex(l => l.selector === SelectorKey.prof)
            if (_index !== -1) {
              _topTabbars.splice(_index, 1)
            }
          }
          if (_recruitNews.length <= 0) {
            const _index = _topTabbars.findIndex(l => l.selector === SelectorKey.badge)
            if (_index !== -1) {
              _topTabbars.splice(_index, 1)
            }
          }
          if (_news.length <= 0) {
            const _index = _topTabbars.findIndex(l => l.selector === SelectorKey.news)
            if (_index !== -1) {
              _topTabbars.splice(_index, 1)
            }
          }
          this.extData.subjects = _subjects
          const subjects__show = this.extData.subjects.slice(0, proPageSize)
          const { subjectPagination } = this.state
          const description = retData.description
          const detail = {
            id: retData.id,
            name: retData.name,
            logo: retData.logo,
            province: retData.province,
            features: retData.features || [],
            level: retData.level,
            department: retData.department,
            banner: retData.banner,
            description
          }
          this.setState(
            {
              topTabbars: _topTabbars,
              detail,
              subjects__show,
              recruitNews: _recruitNews,
              news: _news,
              agencys: retData.agencys || [],
              schools: retData.schools || [],
              topics: _topics,
              subjectPagination: {
                ...subjectPagination,
                pageCount: Math.ceil(this.extData.subjects.length / proPageSize)
              }
            },
            () => {
              // Taro.showNavigationBarLoading()
              // setTimeout(() => {
              //   this.doLayoutAction()
              // }, 1000)
              this.extData.dateFetched = true
            }
          )
          this.setPageInfo(detail)
        }
      })
      .finally(() => {
        Taro.hideLoading()
      })
  }
  handleProPageChange = (page: number) => {
    const _pagination = cloneDeep(this.state.subjectPagination)
    _pagination.page = page
    this.setState({
      subjectPagination: _pagination,
      subjects__show: this.extData.subjects.slice((page - 1) * proPageSize, page * proPageSize)
    })
  }
  pageScrollHandler(options: Taro.PageScrollObject) {
    if (this.extData.handleScrollTriggered) return
    console.log("pageScrollHandler----", options)
    const { scrollTop } = options
    const { topTabbars } = this.state
    let tabSelect: INullable<ITopTabbar> = null
    for (let i = topTabbars.length - 1; i >= 0; i--) {
      const cur = topTabbars[i]
      if (scrollTop >= (cur.scrollTop as number)) {
        tabSelect = cur
        break
      }
    }
    if (tabSelect) {
      this.setState({
        currentActiveTab: tabSelect.selector
      })
    }
    // 吸顶时给顶部tabbar加阴影
    if (this.extData.topTabbarsTop && scrollTop >= this.extData.topTabbarsTop) {
      if (!this.state.topTabbarShadow) {
        this.setState({
          topTabbarShadow: true
        })
      }
    } else {
      if (this.state.topTabbarShadow) {
        this.setState({
          topTabbarShadow: false
        })
      }
    }
  }
  onPageScroll(options: Taro.PageScrollObject) {
    if (this.extData.handleScrollTriggered) return
    this.pageScrollHandler(options)
  }
  getTopTabbarsHeight = () => {
    return new Promise(resolve => {
      if (this.extData.topTabbarsHeight) {
        return resolve(this.extData.topTabbarsHeight)
      }
      Taro.createSelectorQuery()
        .select("#topTabbars")
        .boundingClientRect()
        .exec(res => {
          this.extData.topTabbarsHeight = res[0].height
          this.extData.topTabbarsTop = res[0].top
          resolve(this.extData.topTabbarsHeight)
        })
    })
  }
  flushScrollTop = () => {
    Taro.nextTick(() => {
      this.getTopTabbarsHeight().then(() => {
        const topTabbarsHeight = this.extData.topTabbarsHeight
        const query = Taro.createSelectorQuery()
        const topTabbars = cloneDeep(this.state.topTabbars)
        for (let i = 0; i < topTabbars.length; i++) {
          query.select("#" + topTabbars[i].selector).boundingClientRect()
        }
        query.exec(res => {
          for (let i = 0; i < res.length; i++) {
            if (i > 0) {
              topTabbars[i].scrollTop = Math.floor(res[i].top - topTabbarsHeight)
            } else {
              topTabbars[i].scrollTop = Math.floor(res[i].top)
            }
          }
          this.setState({
            topTabbars
          })
        })
      })
    })
  }
  determineWXParseFold = () => {
    Taro.createSelectorQuery()
      .select("#school-cont")
      .boundingClientRect(async rect => {
        await this.getTopTabbarsHeight()
        const htmlContentMaxHeight = this.extData.windowAvailableHeight - this.extData.topTabbarsTop
        this.setState(
          {
            htmlContentHeight: rect.height,
            htmlContentMaxHeight
          },
          () => {
            // Taro.hideNavigationBarLoading()
            this.flushScrollTop()
          }
        )
      })
      .exec()
  }
  handleExpandHtmlContent = () => {
    this.setState(
      {
        showAllHtmlContent: true
      },
      () => {
        this.flushScrollTop()
      }
    )
  }
  // 学校简介
  renderSummary = () => {
    const { detail, htmlContentHeight, showAllHtmlContent, htmlContentMaxHeight } = this.state
    const styleObj = {} as React.CSSProperties
    if (htmlContentHeight > htmlContentHeightThreshold && !showAllHtmlContent) {
      styleObj.maxHeight = `${htmlContentMaxHeight}px`
    }
    return (
      <View className="pt-35px px-30px bg-hex-fff">
        <View className="relative" id={SelectorKey.intro}>
          <View
            className={clsx(
              "yahei font-normal text-28px text-hex-2c2c35 leading-48px overflow-hidden"
            )}
            style={styleObj}
          >
            {/* {
              "max-h-560px": htmlContentHeight > htmlContentHeightThreshold && !showAllHtmlContent
            } */}
            {/* <View
              dangerouslySetInnerHTML={{ __html: detail?.description as string }}
              className="taro_html"
            ></View> */}
            {detail?.description && (
              <View className="taro_html">
                <GpHtmlRenderer htmlBlocks={detail?.description?.blocks} />
              </View>
            )}
          </View>
          {/* 展开按钮 */}
          {htmlContentHeight > htmlContentHeightThreshold && !showAllHtmlContent ? (
            <View className={styles["expand-wrap"]} hoverClass="none">
              <View className={styles["expand-wrap-mask"]}></View>
              <View
                className="flex flex-row justify-center items-center cursor-pointer"
                hoverClass="none"
                onClick={this.handleExpandHtmlContent}
              >
                <View
                  className="yahei font-normal text-28px text-hex-3c88f7 ml-12px"
                  hoverClass="none"
                >
                  展开全部
                </View>
                <ArrowDown
                  color="#3c88f7"
                  style={{
                    fontSize: arrowSize
                  }}
                />
              </View>
            </View>
          ) : null}
        </View>
      </View>
    )
  }
  render(): React.ReactNode {
    if (!this.state.detail) return null
    const { detail, htmlContentHeight } = this.state
    const len = detail.features?.length
    return (
      <GpContainer>
        {detail ? (
          <View
            id="school-cont"
            className="yahei font-normal text-28px text-hex-2c2c35 leading-48px absolute "
            style={{
              top: -9999,
              zIndex: -20
            }}
          >
            {/* <View
              dangerouslySetInnerHTML={{ __html: detail?.description as string }}
              className="taro_html"
            ></View> */}
            {detail?.description && (
              <View className="taro_html">
                <GpHtmlRenderer htmlBlocks={detail?.description?.blocks} />
              </View>
            )}
          </View>
        ) : null}
        {/* mask for html */}
        {htmlContentHeight <= 0 ? (
          <View
            className="fixed left-0 top-0 right-0 bottom-0 bg-hex-fff"
            style={{
              zIndex: 9999999
            }}
            catchMove
          ></View>
        ) : null}
        {/* 背景 */}
        <View
          className="bg-image w-750px h-248px box-border pl-30px pt-40px relative"
          style={{
            backgroundImage: `url(${detail.banner})`
          }}
        >
          <View className={styles["mask-bg"]}></View>
          <View className="h-150px  box-border flex flex-row items-center relative">
            <Image src={detail.logo} className="w-150px h-150px rounded-16px" mode="aspectFit" />
            <View className="h-full flex flex-col justify-between ml-32px">
              <View className="flex flex-row items-center">
                <View className="yahei font-normal text-36px text-hex-fff mr-12px">
                  {detail.name}
                </View>
                <View
                  className="yahei font-normal text-22px text-hex-fff h-32px box-border rounded-4px px-10px leading-32px"
                  style={{
                    backgroundColor: "rgba(255, 255, 255, 0.3)"
                  }}
                >
                  {detail.province}
                </View>
              </View>
              <View className="flex flex-row">
                {detail.features &&
                  detail.features.map((l, index) => (
                    <View
                      key={index}
                      className={clsx("yahei", styles["tag"], {
                        [styles["active"]]: index === 0,
                        "mr-8px": index !== len - 1
                      })}
                    >
                      {l}
                    </View>
                  ))}
              </View>
              <View className="yahei font-normal text-24px text-hex-fff">
                主管部门:{detail.department}
              </View>
            </View>
          </View>
        </View>
        {/* 主页面内容 */}
        <View className={styles["main-container"]}>
          {/* 顶部tabbar */}
          {this.renderTopTabbar()}
          {/* 学校简介 */}
          {this.renderSummary()}
          {/* 招生专业 */}
          {this.renderProfessional()}
          {/* 招生简章 */}
          {this.renderBadge()}
          {/* 相关资讯 */}
          {this.renderNews()}
          {/* 推荐机构 */}
          {this.renderInstitution()}
          {/* 周边院校 */}
          {this.renderSchool()}
          {/* 艺考专题 */}
          {this.renderExamColumn()}
          {/*  快捷导航*/}
          {this.renderJumpNavs()}
          {/* 当前位置 */}
          <GpCurrentPort ports={ports} />
        </View>
        {/* 底部tabbar */}
        <GpSimpleTabbar />
      </GpContainer>
    )
  }
}
export default SchoolDetail
